require "app/helpers/application_helper.rb"
require "config/cdr_config.rb"
require 'date'
require 'time'

class CdrController < ApplicationController
  layout "cdr_explorer"
  
  def test_chart
    response.content_type = Mime::HTML
    @arr_data = [["vcb11",56,45,46,32], ["vcb2", 44, 67,34,23], ["vcb3", 23, 89, 90, 45]]
    @arr_data2 = [56,45,46,32]
  end
  
  def detail
    response.content_type = Mime::HTML
    vcb       = params[:id].gsub("_",".")
    view_name = get_view_name_for_cdr(params[:date].gsub("_","\/"))
    
    #################################################
    ##
    ## Gets Filtered data if the filter is applied
    ## watch the variable named 'where'
    ##
    #################################################
   
    ########################
    ## Filter 1 Date
    ## a view is already created when a cdr file is parsed
    ## e.g. create view CDR0810 as (select * from cdr_raws where cast(c1_start_time as date) >='2011-08-10' and cast(c1_start_time as date) < '2011-08-11');
    ########################      
    where =  "where c28_call_dest_regid='%s'" % [vcb]
    
    ########################
    ## Filter 2 Max R-Factor
    ########################
    if params[:rfactor] != nil
      begin
        r = Integer(params[:rfactor])
        where += " and cast(c74_rfactor_on_dest_leg as integer) < %d" % r
      rescue
        # do nothing
      end
    end
    ########################
    ## Filter 3 Min Duration
    ########################
    ## select date_part('second', cast('000:03:45' as time)) # time format is very tricky
    if params[:duration] != nil
      begin
        d = Integer(params[:duration])
        where += " and (date_part('hour', cast(c3_call_duration as time))*3600 + date_part('min', cast(c3_call_duration as time))*60 + date_part('second', cast(c3_call_duration as time))) > %d" % d
      rescue
        # do nothing
      end
      
    end
    
    @sql = "select c2_start_time, c1_start_time, c74_rfactor_on_dest_leg, c71_pdv_on_dest_leg, c69_packets_lost_on_dest_leg from #{view_name} #{where} order by cast(c2_start_time as integer) DESC"
    puts @sql; # for debugging
    @data = CdrRaw.find_by_sql(@sql)
    @r_factor            = {}
    @packet_loss         = {}
    @pdv                 = {}
    
    @r_factor_gtable    = {}
    @pdv_gtable         = {}
    for d in @data
      date = Time.at Integer d.c2_start_time
      key = [date.strftime("%a"), date.strftime("hour%H")]
      
      @r_factor_gtable[Integer d.c2_start_time] = d.c74_rfactor_on_dest_leg if d.c74_rfactor_on_dest_leg != nil and d.c74_rfactor_on_dest_leg.size != 0
      @pdv_gtable[Integer d.c2_start_time]      = d.c71_pdv_on_dest_leg     if d.c71_pdv_on_dest_leg != nil and d.c71_pdv_on_dest_leg.size != 0
      
      if @r_factor.has_key?(key)
        @r_factor[key] += Integer d.c74_rfactor_on_dest_leg
      else
        @r_factor[key] = Integer d.c74_rfactor_on_dest_leg
      end
      if @pdv.has_key?(key)
        @pdv[key] += Integer d.c71_pdv_on_dest_leg
      else
        @pdv[key] = Integer d.c71_pdv_on_dest_leg
      end
      if @packet_loss.has_key?(key)
        @packet_loss[key] += Integer d.c69_packets_lost_on_dest_leg
      else
        @packet_loss[key] = Integer d.c69_packets_lost_on_dest_leg
      end
      
    end
    
  end
  
  def get_view_name_for_cdr(param_date)
    
    #setting the default
    format = "CDR%Y%m%d"
    default_name = (Time.now() - 3600*24).strftime(format) # yesterday output example: CDR19800311
    #puts default_name
    
    begin 
      if param_date == nil
        return default_name
      end
      d = DateTime.parse(param_date) 
    rescue 
      return default_name
    end
    
    return d.strftime(format)
    
    
    
  end
  
  def index
    response.content_type = Mime::HTML
    @per_b        = Array.new
    @r_factor     = Hash.new
    @stat_per_bridge_r_factor = Hash.new
    @stat_per_bridge_pdv = Hash.new
    @stat_per_bridge_packet_loss = Hash.new
    
    @data_centers = DATA_CENTERS  #from config ["iad", "sjc", "las", "ord", "nyc"] # TODO: add more, do I need dynamic? or static?
    
    @arr_data = []                #the format is very important!! it is used by vcb.builder in the view
    
    @bridge_count = 0             #to make the size of the chart
    for b in bridges
      #################################################
      
      #################################################
      ##
      ## Gets Filtered data if the filter is applied
      ## watch the variable named 'where'
      ##
      #################################################
      ## cdr_raw = CdrRaw.new("cdr_raw") TODO this does not work, then how?
      #t = cdr_raw.find(:all, :conditions => ["c28_call_dest_regid=?", b.c28_call_dest_regid], :order=>"cast(c2_start_time as integer) DESC")
      #t = CdrRaw.find(:all, :conditions => ["c28_call_dest_regid=?", b.c28_call_dest_regid], :order=>"cast(c2_start_time as integer) DESC")
      
      
      ########################
      ## Filter 1 Date
      ## a view is already created when a cdr file is parsed
      ## e.g. create view CDR0810 as (select * from cdr_raws where cast(c1_start_time as date) >='2011-08-10' and cast(c1_start_time as date) < '2011-08-11');
      ########################      
      view_name = get_view_name_for_cdr(params[:date]) # This function should be used for creating a view when cdr file is parsed.
      where =  "where c28_call_dest_regid='%s'" % [b.c28_call_dest_regid]
      
      ########################
      ## Filter 2 Max R-Factor
      ########################
      if params[:rfactor] != nil
        begin
          r = Integer(params[:rfactor])
          where += " and cast(c74_rfactor_on_dest_leg as integer) < %d" % r
        rescue
          # do nothing
        end
      end
      ########################
      ## Filter 3 Min Duration
      ########################
      ## select date_part('second', cast('000:03:45' as time)) # time format is very tricky
      if params[:duration] != nil
        begin
          d = Integer(params[:duration])
          where += " and (date_part('hour', cast(c3_call_duration as time))*3600 + date_part('min', cast(c3_call_duration as time))*60 + date_part('second', cast(c3_call_duration as time))) > %d" % d
        rescue
          # do nothing
        end
        
      end
      
      selected_data_centers = []
      if params["all"] == "1"
        for dc in DATA_CENTERS
          selected_data_centers << "c28_call_dest_regid like '%s'" % ("%"+dc)
        end
      else
        for dc in DATA_CENTERS
          #puts "c28_call_dest_regid like '%s'" % ("%"+dc) if params[dc].to_s == "1" #debug
          selected_data_centers << "c28_call_dest_regid like '%s'" % ("%"+dc) if params[dc].to_s == "1"
        end  
      end
      
      temp = selected_data_centers.join(" or ").to_s
      where += " and (%s)" % temp if selected_data_centers.size !=0 and selected_data_centers =! nil
      
      
      
      @sql = "select * from #{view_name} #{where} order by cast(c2_start_time as integer) DESC"
      #puts @sql; return # for debugging
      t = CdrRaw.find_by_sql(@sql)
      
      
      if params[:all] != "1" and t != nil and t.size != 0
        @bridge_count += 1
        @per_b << t
        dest_vcb                = b # same as t[0].c28_call_dest_regid
        @r_factor[dest_vcb]     = Array.new
        temp_hash_r_factor_dest = Hash.new
        temp_hash_r_factor_src  = Hash.new
        temp_array_r_factor     = []
        temp_array_pdv          = Array.new
        temp_array_packet_loss  = Array.new
        
        
        arr_data_inner = [b.c28_call_dest_regid.to_s]
        
        for item in t
          if item.c2_start_time !=nil and item.c2_start_time.size != 0 # TODO pay attention
            time_index = Time.at(Integer item.c2_start_time).strftime("%m/%d/%Y") #TODO: how to sort?
            temp_hash_r_factor_dest[time_index]   = Array.new if !temp_hash_r_factor_dest.has_key?(time_index)
            temp_hash_r_factor_dest[time_index]   << Integer(item.c74_rfactor_on_dest_leg) if item.c74_rfactor_on_dest_leg != nil and item.c74_rfactor_on_dest_leg.size != 0
            temp_hash_r_factor_src[time_index]    = Array.new if !temp_hash_r_factor_src.has_key?(time_index)
            temp_hash_r_factor_src[time_index]    << Integer(item.c67_rfactor_on_src_leg) if item.c67_rfactor_on_src_leg != nil and item.c67_rfactor_on_src_leg.size != 0
            begin
              temp_array_r_factor << Integer(item.c74_rfactor_on_dest_leg)          if item.c74_rfactor_on_dest_leg       != nil and item.c74_rfactor_on_dest_leg.strip.size      != 0
              temp_array_pdv          << Integer(item.c71_pdv_on_dest_leg)          if item.c71_pdv_on_dest_leg           != nil and item.c71_pdv_on_dest_leg.strip.size          != 0
              temp_array_packet_loss  << Integer(item.c69_packets_lost_on_dest_leg) if item.c69_packets_lost_on_dest_leg  != nil and item.c69_packets_lost_on_dest_leg.strip.size != 0
              arr_data_inner      << Integer(item.c74_rfactor_on_dest_leg)          if item.c74_rfactor_on_dest_leg       != nil and item.c74_rfactor_on_dest_leg.strip.size      != 0
            rescue
              log("cdr_controller", "invalid string for integer: %s, %s, %s, %s" % [item.c74_rfactor_on_dest_leg, item.c71_pdv_on_dest_leg, item.c69_packets_lost_on_dest_leg, item.c74_rfactor_on_dest_leg])
            end
          end
        end
        
        @arr_data << arr_data_inner
        
        d = temp_hash_r_factor_dest.sort
        s = temp_hash_r_factor_src.sort
        
        
        
        begin
          label = b.c28_call_dest_regid
          min   = temp_array_r_factor.min
          avg   = temp_array_r_factor.inject(0){|acc, el| acc + el} / temp_array_r_factor.length.to_f
          med   = median(temp_array_r_factor)
          max   = temp_array_r_factor.max
          @stat_per_bridge_r_factor[label] = "['%s', %s, %s, %s, %s]" % [label, min, avg, med, max]
          
          min   = temp_array_pdv.min
          avg   = temp_array_pdv.inject(0){|acc, el| acc + el} / temp_array_pdv.length.to_f
          med   = median(temp_array_pdv)
          max   = temp_array_pdv.max
          @stat_per_bridge_pdv[label] = "['%s', %s, %s, %s, %s]" % [label, min, avg, med, max]
          
          min   = temp_array_packet_loss.min
          avg   = temp_array_packet_loss.inject(0){|acc, el| acc + el} / temp_array_packet_loss.length.to_f
          med   = median(temp_array_packet_loss)
          max   = temp_array_packet_loss.max
          @stat_per_bridge_packet_loss[label] = "['%s', %s, %s, %s, %s]" % [label, min, avg, med, max]
        end
        
        i=0
        while i < d.size or i < s.size
          if i < d.size
            h     = d[i]
            label = h[0]
            min   = h[1].min
            avg   = h[1].inject(0){|acc, el| acc + el} / h[1].length.to_f
            med   = median(h[1])
            max   = h[1].max
            @r_factor[dest_vcb] <<  "['D%s', %s, %s, %s, %s]" % [label, min, avg, med, max] #TODO tricky, need to clean the code
          end
          
          if i < s.size
            h     = s[i]
            label = h[0]
            min   = h[1].min
            avg   = h[1].inject(0){|acc, el| acc + el} / h[1].length.to_f
            med   = median(h[1])
            max   = h[1].max
            @r_factor[dest_vcb] <<  "['S%s', %s, %s, %s, %s]" % [label, min, avg, med, max] #TODO tricky, need to clean the code
          end # end if
          
          i += 1
        end # end while i < d.size or i < s.size
      end # end if params[:all] != "1" and t != nil and t.size != 0
    end # end for b in bridges
  end
  
  
  def pdv
    @per_b        = Array.new
    @pdv     = Hash.new
    for b in bridges
      t = CdrRaw.find(:all, :conditions => ["c28_call_dest_regid=?", b.c28_call_dest_regid], :order=>"cast(c2_start_time as integer) DESC")
      
      @per_b << t
      dest_vcb                = t[0].c28_call_dest_regid
      @pdv[dest_vcb]     = Array.new
      temp_hash_pdv_dest      = Hash.new
      temp_hash_pdv_src      = Hash.new
      
      for item in t        
        time_index = Time.at(Integer item.c2_start_time).strftime("%m/%d/%Y") #TODO: how to sort?
        temp_hash_pdv_dest[time_index]   = Array.new if !temp_hash_pdv_dest.has_key?(time_index)
        temp_hash_pdv_dest[time_index]   << Integer(item.c71_pdv_on_dest_leg) if item.c71_pdv_on_dest_leg != nil and item.c71_pdv_on_dest_leg.size != 0
        temp_hash_pdv_src[time_index]    = Array.new if !temp_hash_pdv_src.has_key?(time_index)
        temp_hash_pdv_src[time_index]    << Integer(item.c64_pdv_on_src_leg) if item.c64_pdv_on_src_leg != nil and item.c64_pdv_on_src_leg.size != 0
      end
      
      d = temp_hash_pdv_dest.sort
      s = temp_hash_pdv_src.sort
      
      i = 0
      while i < d.size or i < s.size
        if i < d.size
          h     = d[i]
          label = h[0]
          min   = h[1].min
          avg   = h[1].inject(0){|acc, el| acc + el} / h[1].length.to_f
          med   = median(h[1])
          max   = h[1].max
          @pdv[dest_vcb] <<  "['D%s', %s, %s, %s, %s]" % [label, min, avg, med, max] #TODO tricky, need to clean the code
        end
        
        if i < s.size
          h     = s[i]
          label = h[0]
          min   = h[1].min
          avg   = h[1].inject(0){|acc, el| acc + el} / h[1].length.to_f
          med   = median(h[1])
          max   = h[1].max
          @pdv[dest_vcb] <<  "['S%s', %s, %s, %s, %s]" % [label, min, avg, med, max] #TODO tricky, need to clean the code
        end # end if
        
        i += 1
      end # end while
    end
  end
  
  
  
  def packet_loss
    @per_b           = Array.new
    @packet_loss     = Hash.new
    for b in bridges
      t = CdrRaw.find(:all, :conditions => ["c28_call_dest_regid=?", b.c28_call_dest_regid], :order=>"cast(c2_start_time as integer) DESC")
      
      @per_b << t
      dest_vcb                       = t[0].c28_call_dest_regid
      @packet_loss[dest_vcb]         = Array.new
      temp_hash_packet_loss_dest     = Hash.new
      temp_hash_packet_loss_src      = Hash.new
      
      for item in t        
        time_index = Time.at(Integer item.c2_start_time).strftime("%m/%d/%Y") #TODO: how to sort?
        temp_hash_packet_loss_dest[time_index]   = Array.new if !temp_hash_packet_loss_dest.has_key?(time_index)
        temp_hash_packet_loss_dest[time_index]   << Integer(item.c69_packets_lost_on_dest_leg) if item.c69_packets_lost_on_dest_leg != nil and item.c69_packets_lost_on_dest_leg.size != 0
        temp_hash_packet_loss_src[time_index]    = Array.new if !temp_hash_packet_loss_src.has_key?(time_index)
        temp_hash_packet_loss_src[time_index]    << Integer(item.c62_packets_lost_on_src_leg) if item.c62_packets_lost_on_src_leg != nil and item.c62_packets_lost_on_src_leg.size != 0
      end
      
      d = temp_hash_packet_loss_dest.sort
      s = temp_hash_packet_loss_src.sort
      
      i=0
      while i < d.size or i < s.size
        if i < d.size
          h     = d[i]
          label = h[0]
          min   = h[1].min
          avg   = h[1].inject(0){|acc, el| acc + el} / h[1].length.to_f
          med   = median(h[1])
          max   = h[1].max
          @packet_loss[dest_vcb] <<  "['D%s', %s, %s, %s, %s]" % [label, min, avg, med, max] #TODO tricky, need to clean the code
        end
        
        if i < s.size
          h     = s[i]
          label = h[0]
          min   = h[1].min
          avg   = h[1].inject(0){|acc, el| acc + el} / h[1].length.to_f
          med   = median(h[1])
          max   = h[1].max
          @packet_loss[dest_vcb] <<  "['S%s', %s, %s, %s, %s]" % [label, min, avg, med, max] #TODO tricky, need to clean the code
        end # end if
        
        i += 1
      end # end while
    end
  end
  
  def median(x)
    return nil if x.empty?
    array = x.sort
    m_pos = array.size / 2
    return array.size % 2 == 1 ? array[m_pos] : array[Integer(m_pos-0.5)]
  end
  
  def bridges
    CdrRaw.find(:all, :select=>"distinct(c28_call_dest_regid) as c28_call_dest_regid", :conditions=>"c28_call_dest_regid != null or length(trim(c28_call_dest_regid)) != 0")
  end
  
  def myInteger(s)
    if s==nil or s.size==0
      return 0
    else
      return Integer(s)
    end
  end
end
